
#include "../queue.h"
#include "../driver.h"



#define ERROR result=-1; goto END

#define num 8

int main( int argc, char *argv[] )
{
	int          result  = 0;
	ocl_driver * OpenCL  = NULL; 
	ocl_context  context = OCL_CONTEXT_INIT;
	ocl_code     sources = OCL_CODE_INIT;
	ocl_program  program = OCL_PROGRAM_INIT;
	ocl_kernel   kernel  = OCL_KERNEL_INIT;
	ocl_buffer   results = OCL_BUFFER_INIT;
	Real         check[num] ;
	register cl_uint i;

	memset( check, 0, num*sizeof(Real) );
	
	if( argc > 1 && ! strcmp( "-v", argv[1] ) )
	{
		ocl_logfile = stderr;
	}
	
	OpenCL = ocl_driver_load();
	if( !OpenCL )
	{
		ocl_perror( stderr, "create OpenCL" );
		ERROR;
	}
	
	if( ocl_context_load( &context, OpenCL->platforms[0].num_devices, OpenCL->platforms[0].devices_id) < 0 )
	{
		ocl_perror( stderr, "create context");
		ERROR;
	}
	
	if( ocl_code_read( &sources, "builtins.cl" ) < 0 )
	{
		ocl_perror( stderr, "read builtins.cl" );
		ERROR;
	}
	
	if( ocl_program_load_sources( &program, &context, &sources ) < 0 )
	{
		ocl_perror( stderr, "load program sources");
		ERROR;
	}
	
	
	if( ocl_program_compile( &program, ocl_options) < 0 )
	{
		ocl_perror( stderr, "compile program");
		ocl_program_display_build_logs( &program, stderr);
		ERROR;
	}
	else 
	{
		ocl_program_display_build_logs( &program, stderr);
	}
	
	if( ocl_kernel_load( &kernel, &program, "test" ) < 0 )
	{
		ocl_perror( stderr, "kernel load");
		ERROR;
	}
	
	if( ocl_buffer_load( &results, &context, CL_MEM_READ_WRITE, sizeof(Real) * num, NULL) < 0 )
	{
		ocl_perror( stderr, "can't create buffers" );
		ERROR;
	}
	
	OCL_KERNEL_SET_ARGS_INIT(&kernel,arg_index,arg_res);
	OCL_KERNEL_SET_ARG_BUFFER(&results);
	const cl_int __num = num;
	OCL_KERNEL_SET_ARG(cl_int,__num);
	if( arg_res < 0 )
	{
		ocl_perror( stderr, "'%s' arg[%u]", kernel.FUNCTION_NAME, arg_index);
	}
	OCL_KERNEL_SET_ARGS_DONE();
	
	fprintf( stderr, "context.num_devices= %u\n",(unsigned) context.num_devices );
	for(  i=0; i < context.num_devices; ++i )
	{
		ocl_queue          Q = OCL_QUEUE_INIT;
		const cl_device_id d = context.DEVICES[i];
		const ocl_device  *D = ocl_driver_device( d );
		unsigned j;
		fprintf( stderr, "Running on '%s'\n", D->NAME );
		if( ocl_queue_load( &Q, &context, d, 0) < 0 )
		{
			ocl_perror( stderr, "couldn't create queue");
			continue;
		}
		
		if( ocl_enqueue_task( &Q, &kernel, OCL_NO_EVENTS ) < 0 )
		{
			ocl_perror( stderr, "enqueue_task");
			goto DONE;
		}
		
		assert( results.SIZE <= sizeof(check) );
		if( ocl_enqueue_read_buffer(&Q, &results, CL_TRUE, 0, results.SIZE, check, OCL_NO_EVENTS) < 0 )
		{
			ocl_perror( stderr, "reading results");
			goto DONE;
		}
		
		for(  j=0; j < num; ++j )
		{
			fprintf( stderr, "check[%2u]= %g\n", j, check[j] );
		}
		
		
	DONE:
		ocl_queue_quit( &Q );
	}
	
	
END:
	MDS_MEMORY();
	ocl_buffer_quit(  &results );
	ocl_kernel_quit(  &kernel  );
	ocl_program_quit( &program );
	ocl_code_quit( &sources );
	ocl_context_quit( &context );
	ocl_driver_quit();
	MDS_MEMORY();
	return result;
}
